package com.priox.sigar.jsf;

import com.mm.support.mapper.DTOMapperService;
import com.priox.sigar.application.agrupacion.RegistroAgrupacionApp;
import com.priox.sigar.application.checkpoint.RegistroCheckPointApp;
import com.priox.sigar.application.mappers.AgrupacionMapper;
import com.priox.sigar.application.mappers.CuentaContableMapper;
import com.priox.sigar.client.dto.AgrupacionDTO;
import com.priox.sigar.client.dto.CuentaContableDTO;
import com.priox.sigar.client.dto.TasaProvisionDTO;
import com.priox.sigar.client.flt.CuentaContableFlt;
import com.priox.sigar.domain.model.Agrupacion;
import com.priox.sigar.enums.*;
import com.priox.sigar.jsf.util.FindCrudBeanBase;
import org.apache.commons.lang.StringUtils;
import org.primefaces.event.CloseEvent;
import org.primefaces.event.SelectEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


@ManagedBean
@Scope("session")
@Component
public class MaestroAgrupacionJsfBean extends FindCrudBeanBase {

    private static final Logger LOG = LoggerFactory.getLogger(MaestroAgrupacionJsfBean.class);
    boolean stateMode;
    AgrupacionDTO filtroBusqueda;
    CuentaContableFlt filtroPick=new CuentaContableFlt();
    AgrupacionDTO nuevoRegistro;
    TasaProvisionDTO nuevaTasaProvision;
    CuentaContableDTO nuevoRegistroDetalle;

    List<AgrupacionDTO> registros = new ArrayList<AgrupacionDTO>();
    List<String> allResponsables = new ArrayList<String>();

    List<CuentaContableDTO> detalle = new ArrayList<CuentaContableDTO>();


    private List<CuentaContableDTO> cuentasPickList;




    @Autowired
    AgrupacionMapper agrupacionMapper;

    @Autowired
    CuentaContableMapper cuentaContableMapper;

    @Autowired
    RegistroAgrupacionApp registroAgrupacionApp;

    @Autowired
    RegistroCheckPointApp registroCheckPointApp;

    @Autowired
    DTOMapperService mapperService;


    @PostConstruct
    public void init() {
        filtroBusqueda = new AgrupacionDTO();
        nuevoRegistro = new AgrupacionDTO();
        findRegistros();


    }

    /*Métodos de herencia*/

    @Override
    public void setCursorTableNull() {

    }

    public void showTasaProvision(ActionEvent actionEvent) {
        nuevoRegistro.buildTasaProvision();
    }

    public void showNewDialogSeleccion(ActionEvent actionEvent) {
        filtroPick = new CuentaContableFlt();
        cuentasPickList = new ArrayList<CuentaContableDTO>();
        executeModal("wvSeleccionDialog", true);
    }

    @Override
    public void onShowEditDialog(ActionEvent actionEvent) {
        setUpdateMode(true);
        setPersistMode(true);
        allResponsables=agrupacionMapper.findResponsables();
        nuevoRegistro = registroAgrupacionApp.findById(nuevoRegistro.getAgrupacionId());
    }


    public List<String> onShowResponsable(String filtro) {

        List<String> result= new ArrayList<String>();
        for (Iterator<String> iterator = allResponsables.iterator(); iterator.hasNext(); ) {
            String next = iterator.next();
            if(StringUtils.startsWith(next,filtro)){
                result.add(next);
            }
        }
        return result;
    }


    public void seleccionar(ActionEvent actionEvent) {

        List<String> seleccionados = new ArrayList<String>();

        for (CuentaContableDTO cuentaContableDTO : cuentasPickList) {
            if (cuentaContableDTO.isSeleccionado()) {
                seleccionados.add(cuentaContableDTO.getCuentaContableId());
            }
        }
        nuevoRegistro.getCuentaContables().addAll(registroAgrupacionApp.findByIdList(seleccionados));

        String dialogName = (String) actionEvent.getComponent().getAttributes().get("dialogName");
        if (dialogName != null) {
//            executeModal(dialogName, false);
        }
        findActionSelect(actionEvent);
    }

    public void cleanActionSelect(ActionEvent actionEvent) {
        cuentasPickList = new ArrayList<CuentaContableDTO>();
        filtroPick = new CuentaContableFlt();
    }


    @Override
    public void onNewRecord(ActionEvent actionEvent) {
        setUpdateMode(false);
        allResponsables=agrupacionMapper.findResponsables();
        nuevoRegistro = new AgrupacionDTO();
        nuevoRegistro.setEstado(ActivoInactivo.ACTIVO);
    }

    public void onSelectTipoCuenta() {

    }

    public void initForm(ActionEvent actionEvent) {


    }

    @Override
    public void onFind(ActionEvent actionEvent) {
        findRegistros();
    }

    public TipoCuentaOperacion[] getAllTipoOperacion() {
        return TipoCuentaOperacion.values();
    }

    public void findActionSelect(ActionEvent actionEvent) {
        List<String> ids = new ArrayList<String>();
        for (CuentaContableDTO cuentaContableDTO : nuevoRegistro.getCuentaContables()) {
            ids.add(cuentaContableDTO.getCuentaContableId());
        }
        LOG.debug("CRITERIO DE BUSQUEDA "+filtroPick);
        filtroPick.setTipoCuenta(nuevoRegistro.getTipo());
        filtroPick.setNotInCuentaList(ids);
//        filtroPick.setOpcion(TipoVisible.VISIBLE);
        cuentasPickList = cuentaContableMapper.findByFilter(filtroPick);
        if (cuentasPickList.size() == 0) {
            addMessage(noRecordFoundMsg, FacesMessage.SEVERITY_INFO);
        }
    }

    public void deleteDetailAction(ActionEvent actionEvent) {
        nuevoRegistro.getCuentaContables().remove(nuevoRegistroDetalle);
    }


    public void findRegistros() {
        filtroBusqueda.setUsuarioId(getUser().getUsuarioId());
        registros = agrupacionMapper.findByUsuarioId(filtroBusqueda);
        detalle = new ArrayList<CuentaContableDTO>();
        if (registros.size() == 0) {
            addMessage(noRecordFoundMsg, FacesMessage.SEVERITY_INFO);
        }
    }


    @Override
    public void onClean(ActionEvent actionEvent) {
        registros = new ArrayList<AgrupacionDTO>();
        nuevoRegistro = new AgrupacionDTO();
        filtroBusqueda = new AgrupacionDTO();
    }


    public void onSelectDetail(SelectEvent actionEvent) {
        detalle = cuentaContableMapper.findByAgrupacionId(nuevoRegistro.getAgrupacionId());
    }

    @Override
    public void onPersist(ActionEvent actionEvent) {
        String idComponente = actionEvent.getComponent().getClientId();
        if ("cmdGuardarTp".equals(idComponente)) {
            nuevoRegistro.asignarTasaProvision();
        } else {
            Agrupacion agrupacion = mapperService.map(nuevoRegistro, Agrupacion.class);
            agrupacion.setUsuarioId(getUser().getUsuarioId());
            if(StringUtils.isNotBlank(agrupacion.getResponsable())){
                agrupacion.setResponsable(agrupacion.getResponsable().toUpperCase());
            }
            registroAgrupacionApp.save(agrupacion, updateMode);

            registroAgrupacionApp.updateTipoCategoria(agrupacion);
            findRegistros();
        }
    }

    public boolean isSelectRow() {
        for (AgrupacionDTO agrupacionDTO : registros) {
            if (agrupacionDTO.getSeleccionado()) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void onDeleteSelect(ActionEvent actionEvent) {
        String idComponente = actionEvent.getComponent().getClientId();

        if (idComponente.contains("cmdEliminarCuenta")) {
            List<CuentaContableDTO> list = nuevoRegistro.getCuentaContables();
            List<CuentaContableDTO> remove = new ArrayList<CuentaContableDTO>();
            for (CuentaContableDTO contableDTO : list) {
                if (contableDTO.isSeleccionado()) {
                    remove.add(contableDTO);
                }
            }
            list.removeAll(remove);
            return;
        }


        for (AgrupacionDTO agrupacionDTO : registros) {
            if (agrupacionDTO.getSeleccionado()) {
                Agrupacion agrupacion = mapperService.map(agrupacionDTO, Agrupacion.class);
                registroAgrupacionApp.delete(agrupacion);
            }
        }
        registroCheckPointApp.updateCheckPoints(getUser().getUsuarioId());
        detalle = new ArrayList<CuentaContableDTO>();

    }

    @Override
    public void onDelete(ActionEvent actionEvent) {
        Agrupacion agrupacion = mapperService.map(nuevoRegistro, Agrupacion.class);
        registroAgrupacionApp.delete(agrupacion);
        detalle = new ArrayList<CuentaContableDTO>();
    }

    @Override
    protected void onDialogClose(CloseEvent event) {

    }

    @Override
    protected void onSelectAll(ActionEvent actionEvent) {
        String idComponente = actionEvent.getComponent().getId();

        if ("cmdSelectAgrupacion".equals(idComponente)) {
            for (AgrupacionDTO agrupacionDTO : registros) {
                agrupacionDTO.setSeleccionado(Boolean.TRUE);
            }
        } else if ("cmdSelectCuenta".equals(idComponente)) {
            for (CuentaContableDTO cuentaContableDTO : nuevoRegistro.getCuentaContables()) {
                cuentaContableDTO.setSeleccionado(Boolean.TRUE);
            }
        }
    }

    @Override
    protected void onUnSelectAll(ActionEvent actionEvent) {
        String idComponente = actionEvent.getComponent().getId();
        if ("cmdUnSelectAgrupacion".equals(idComponente)) {
            for (AgrupacionDTO agrupacionDTO : registros) {
                agrupacionDTO.setSeleccionado(Boolean.FALSE);
            }
        } else if ("cmdUnSelectCuenta".equals(idComponente)) {
            for (CuentaContableDTO cuentaContableDTO : nuevoRegistro.getCuentaContables()) {
                cuentaContableDTO.setSeleccionado(Boolean.FALSE);
            }
        }
    }

    /*Getters and Setters*/


    public boolean isStateMode() {
        return stateMode;
    }

    public void setStateMode(boolean stateMode) {
        this.stateMode = stateMode;
    }

    public AgrupacionDTO getFiltroBusqueda() {
        return filtroBusqueda;
    }

    public void setFiltroBusqueda(AgrupacionDTO filtroBusqueda) {
        this.filtroBusqueda = filtroBusqueda;
    }

    public AgrupacionDTO getNuevoRegistro() {
        return nuevoRegistro;
    }

    public void setNuevoRegistro(AgrupacionDTO nuevoRegistro) {
        this.nuevoRegistro = nuevoRegistro;
    }


    public List<CuentaContableDTO> getDetalle() {
        return detalle;
    }

    public void setDetalle(List<CuentaContableDTO> detalle) {
        this.detalle = detalle;
    }

    public List<AgrupacionDTO> getRegistros() {
        return registros;
    }

    public void setRegistros(List<AgrupacionDTO> registros) {
        this.registros = registros;
    }

    public List<CuentaContableDTO> getCuentasPickList() {
        return cuentasPickList;
    }

    public void setCuentasPickList(List<CuentaContableDTO> cuentasPickList) {
        this.cuentasPickList = cuentasPickList;
    }

    public CuentaContableFlt getFiltroPick() {
        return filtroPick;
    }

    public void setFiltroPick(CuentaContableFlt filtroPick) {
        this.filtroPick = filtroPick;
    }

    public TipoCuenta[] getAllTipoCuenta() {
        TipoCuenta[] result = new TipoCuenta[3];
        result[0] = TipoCuenta.CUENTA_X_COBRAR;
        result[1] = TipoCuenta.CUENTA_X_PAGAR;
        result[2] = TipoCuenta.CUENTA_ALMACEN;
        return result;

    }

    public ActivoInactivo[] getAllEstado() {
        return ActivoInactivo.values();
    }

    public TipoSigno[] getAllSigno() {
        return TipoSigno.values();
    }

    public CuentaContableDTO getNuevoRegistroDetalle() {
        return nuevoRegistroDetalle;
    }

    public void setNuevoRegistroDetalle(CuentaContableDTO nuevoRegistroDetalle) {
        this.nuevoRegistroDetalle = nuevoRegistroDetalle;
    }

    public TasaProvisionDTO getNuevaTasaProvision() {
        return nuevaTasaProvision;
    }

    public void setNuevaTasaProvision(TasaProvisionDTO nuevaTasaProvision) {
        this.nuevaTasaProvision = nuevaTasaProvision;
    }

    public List<String> getAllResponsables() {
        return allResponsables;
    }

    public void setAllResponsables(List<String> allResponsables) {
        this.allResponsables = allResponsables;
    }
}
